module GYLite
{
		
			
	/**羔羊缓动类*/
	export class GYTween
	{
		private _startTime:number;
		public delay:number;
		public updateFunc:Function;
		public completeFunc:Function;
		public startFunc:Function;
		public thisObject:any;
		public duration:number=0;
		public target:IResource;
		public tweenArr:Array<TweenData>;		
		private _intervalId:number;
		private _isRunning:boolean;
		private _isReserve:boolean;
		private _completeClear:boolean;
		public keepFrom:boolean;
		
		public constructor()
		{
			var s = this;
			s._startTime=0;
			s.delay=0;
			s.updateFunc=null;
			s.completeFunc=null;
			s.startFunc=null;
			s.thisObject=null;
			s.duration=0;
			s.target=null;
			s.tweenArr=null;
			s._intervalId=-1;
			s._isRunning=false;
			s._isReserve=false;
			s._completeClear=false;
		}
		/**@param s.isReserve 是否翻转播放*/
		public run(isReserve:boolean = false):void
		{var s = this;
			s.stop();			
			if(s._intervalId > -1)
			{
				clearInterval(s._intervalId);				
				s._intervalId = -1;
			}
			if(s.delay > 0)
			{				
				s._intervalId = setTimeout(s.toRun.bind(s),s.delay,isReserve);
			}				
			else
				s.toRun(isReserve);
		}
		public toRun(isReserve:boolean = false):void
		{var s = this;
			s._isReserve = isReserve;
			s._startTime = GYLite.CommonUtil.loopTime;
			var len:number;
			len = s.tweenArr.length;
			while(--len>-1)
			{
				var data:TweenData = s.tweenArr[len];
				if(data.ease==null)data.ease = GYTween.commonEase;
				if(!s.keepFrom)
					if(isNaN(data.initFrom))data.initFrom = s.target[data.propertyName];
				if(s._isReserve)
				{
					data.from = data.initTo;
					data.to = (!s.keepFrom || data.initFrom == data.initFrom)?data.initFrom:s.target[data.propertyName];
				}
				else
				{
					data.from = (!s.keepFrom || data.initFrom == data.initFrom)?data.initFrom:s.target[data.propertyName];
					data.to = data.initTo;
				}
			}			
			if(s.startFunc!=null)s.startFunc.call(s.thisObject);
			if(!s._isRunning)
			{
				CommonUtil.addStageLoop(s.loop,s);
				s._isRunning = true;
				s.loop(s._startTime);
				
			}						
		}
		public stop():void
		{let s = this;			
			if(s._intervalId > -1)
			{
				clearInterval(s._intervalId);				
				s._intervalId = -1;
			}
			if(!s._isRunning)return;
			s._isRunning = false;
			CommonUtil.delStageLoop(s.loop,s);
		}
		public get isRunning():boolean
		{var s = this;
			return s._isRunning;
		}
		private loop(t:number):void
		{var s = this;
			var len:number;
			var compFunc:Function,sObj:any,tar:any;
			if(s.target.disposed)
			{
				s.clear();
				return;
			}
			len = s.tweenArr.length;
			while(--len>-1)
				(s.tweenArr[len] as TweenData).ease(s.tweenArr[len], this);
			if(s.updateFunc!=null)s.updateFunc.call(s.thisObject,s.target);
			if(CommonUtil.loopTime >= s._startTime + s.duration)
			{
				compFunc = s.completeFunc;
				sObj = s.thisObject;
				tar = s.target;
				if(s._completeClear)
					s.clear();
				else
				{
					s._isRunning = false;
					CommonUtil.delStageLoop(s.loop,s);
				}
				if(compFunc!=null)compFunc.call(sObj,tar);
			}
		}
		/**销毁GYTween对象
		 * @param tar 操控的显示对象
		 * */
		public disposeByTarget(tar:any):void
		{
			let len:number;
			len = GYTween._useTween.length;
			while(--len>-1)
			{
				if(GYTween._useTween[len].target == tar)
				{
					GYTween._useTween[len].clear(false);
					GYTween._useTween.splice(len, 1);
				}
			}
		}
		public clear(removeUse:boolean=true):void
		{var s = this;
			if(s.target == null)return;
			GYTween._pool.push(this);
			if(removeUse)
			{
				let ind:number = GYTween._useTween.indexOf(this);
				if(ind > -1)
				{
					GYTween._useTween.splice(ind, 1);
				}
			}			
			var len:number;
			len = s.tweenArr.length;
			while(--len>-1)
				(s.tweenArr[len] as TweenData).clear();
			s.tweenArr = null;
			s.target = null;
			s.duration = 0;
			s.delay = 0;
			s.completeFunc = null;
			s.startFunc = null;
			s.updateFunc = null;
			s.thisObject = null;
			s._isRunning = false;
			s._completeClear = false;
			s._isReserve = false;
			CommonUtil.delStageLoop(s.loop,s);
			if(s._intervalId > -1)
			{
				clearInterval(s._intervalId)				
				s._intervalId = -1;
			}
		}
		public get startTime():number
		{var s = this;
			return s._startTime;
		}

		/**播放完成后自动清理tween*/
		public get completeClear():boolean
		{var s = this;
			return s._completeClear;
		}

		public set completeClear(value:boolean)
		{var s = this;
			s._completeClear = value;
		}

		/**是否翻转播放*/
		public get isReserve():boolean
		{var s = this;
			return s._isReserve;
		}

		/**匀速缓动*/
		public static commonEase(tData:TweenData,t:GYTween):void
		{
			var per:number = t.duration==0?1:((CommonUtil.loopTime - t.startTime)/t.duration);
			if(per > 1)
			{
				per = 1;
				t.target[tData.propertyName] = 	tData.to;
				return;
			}
			t.target[tData.propertyName] = tData.from + (tData.to - tData.from) * per;
		}
		/**加速缓动*/
		public static addEase(tData:TweenData,t:GYTween):void
		{
			var per:number = t.duration==0?1:((CommonUtil.loopTime - t.startTime)/t.duration);
			var s:number = tData.to - tData.from;
			if(per > 1)
			{
				per = 1;
				t.target[tData.propertyName] = 	tData.to;
				return;
			}
			per = per * per;
			t.target[tData.propertyName] = tData.from + s*per;
		}
		/**减速缓动*/
		public static reduceEase(tData:TweenData,t:GYTween):void
		{
			var per:number = 1-(t.duration==0?1:((CommonUtil.loopTime - t.startTime)/t.duration));
			var s:number = tData.to - tData.from;
			if(per < 0)
			{
				per = 0;
				t.target[tData.propertyName] = 	tData.to;
				return;
			}
			per = per * per;
			t.target[tData.propertyName] = tData.from + s*(1 - per);
		}
		private static _pool:GYTween[];	
		private static _useTween:GYTween[]=[];
		public static to(target:any,tweenArr:Array<TweenData>,duration:number,delay:number=0,thisObject:any=null,completeFunc:Function=null,startFunc:Function=null,updateFunc:Function=null,runImmediate:boolean=true,isClear:boolean=true):GYTween
		{
			if(!GYTween._pool)
			{				
				GYTween._pool=new Array<GYTween>();
			}			
			var t:GYTween = (GYTween._pool.length==0?new GYTween():GYTween._pool.pop());
			t.target = target;
			t.tweenArr = tweenArr;
			t.duration = duration;
			t.delay = delay;
			t.completeFunc = completeFunc;
			t.startFunc = startFunc;
			t.updateFunc = updateFunc;
			t.thisObject = thisObject;
			t.completeClear = isClear;
			GYTween._useTween.push(t);
			if(runImmediate)
				t.run();			
			return isClear?null:t;
		}
		
		/***对已经被销毁的对象的tween进行垃圾回收*/
		public static gc():void
		{
			let len:number;
			let tween:GYLite.GYTween;
			len = GYTween._useTween.length;
			while(--len > -1)
			{
				tween = GYTween._useTween[len];
				if(tween.target.disposed)
				{
					tween.clear(false);
					GYTween._useTween.splice(len, 1);
				}					
			}
		}
	}
}